package com.naiterui.ehp.bp.utils.beans;

import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.core.ParameterizedTypeReference;

import com.naiterui.ehp.bp.support.utils.JsonMapper;

public class BeanUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(BeanUtil.class);

    /**
     * 复制属性
     *
     * @param source
     * @param target
     *
     * @return
     *
     * @throws Exception
     */
    public static Object copyProperties(Object source, Object target) {
        try {
            BeanUtils.copyProperties(source, target);
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }
        return target;
    }

    /**
     * 复制属性
     *
     * @param target
     * @param source
     * @param taregtType
     *
     * @return
     *
     * @throws Exception
     */
    public static <T, K> List<T> copyList(List<K> source, List<T> target, Class<T> taregtType) {
        try {
            for (K k : source) {
                T t = taregtType.newInstance();
                BeanUtil.copyProperties(k, t);
                target.add(t);
            }
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }
        return target;
    }

    /**
     * 在拷贝属性时忽略空值
     *
     * @param source the source bean
     * @param target the target bean
     * @param ignore 不管是否有值，肯定忽略的参数
     */
    public static void copyPropertiesIgnoreNull(Object source, Object target, String... ignore) {
        BeanUtils.copyProperties(source, target, getNullPropertyNames(source, ignore));
    }

    /**
     * 获取空的属性名称
     *
     * @param source 源对象
     *
     * @return
     */
    public static String[] getNullPropertyNames(Object source, String... ignore) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<>();
        Collections.addAll(emptyNames, ignore);
        for (java.beans.PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null) {
                emptyNames.add(pd.getName());
            }
        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }

    public static Map<String, Object> describe(Object source) {
        return JsonMapper.toObject(JsonMapper.toJson(source), new ParameterizedTypeReference<Map<String, Object>>() {
        });
    }
}
